﻿using IOP.SgrA;
using IOP.SgrA.SilkNet.Vulkan;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Silk.NET.Vulkan;
using Silk.NET.Vulkan.Extensions.KHR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VkSample111;

public class Startup : ISgrAStartup
{
    public void Configure(IGraphicsBuilder server, IHostEnvironment env)
    {
        server.BuildVulkan((manager) =>
        {
            manager.CreateVulkanInstanceFromConfiguration().CreateDebugReportCallback(DebugReport);
            manager.Logger.LogInformation("创建Vulkan实例成功");
            manager.Logger.LogInformation($"Vulkan硬件设备数量为{manager.PhysicalDevices.Length}个");

            var pDevice = manager.PhysicalDevices[0];
            var lDevice = manager.CreateVulkanDevice(pDevice, (device) =>
            {
                device.Name = "main";
                device.EnabledExtensionNames = new string[] { KhrSwapchain.ExtensionName };
            }, (phyDevice) =>
            {
                QueueFamilyProperties[] properties = phyDevice.GetQueueFamilyProperties();
                manager.Logger.LogInformation($"Vulkan硬件设备支持的队列家族数量为{properties.Length}");
                var result = new List<QueueFamilyIndices>();
                QueueFamilyIndices index = new QueueFamilyIndices();
                for (uint i = 0; i < properties.Length; i++)
                {
                    if (properties[i].QueueFlags.HasFlag(QueueFlags.GraphicsBit))
                    {
                        index.FamilyType |= QueueType.Graphics;
                        if (phyDevice.GetPhysicalDevicePresentationSupport((int)i))
                        {
                            index.FamilyType |= QueueType.Present;
                            index.FamilyIndex = i;
                            result.Add(index);
                            index = new QueueFamilyIndices();
                            continue;
                        }
                    }
                }
                return result.ToArray();
            });
            lDevice.InitWorkQueue((device, indeics) =>
            {
                List<WorkQueue> list = new List<WorkQueue>();
                foreach (var item in indeics)
                {
                    if (item.FamilyType == (QueueType.Graphics | QueueType.Present))
                    {
                        Queue queue = device.GetQueue(item.FamilyIndex, 0);
                        var type = QueueType.Graphics | QueueType.Present;
                        WorkQueue work = new WorkQueue(type, item.FamilyIndex, 0, queue);
                        list.Add(work);
                        return list;
                    }
                }
                return list;
            });
            lDevice.CreateResourcesCommandPool(lDevice.WorkQueues[0].FamilyIndex);
            lDevice.CreatePipelineCache();

            var windowOption = new WindowOption() { Height = 900, Width = 1440, Title = "VkSample111", UpdateRate = 120 };
            var window = manager.CreateWindow<Window>("Main", windowOption).ConfigWindow<Window, WindowConfig>();
            window.AddWapperModules(typeof(RenderPassModule), typeof(PipelineModule), typeof(AssetsModule));
            manager.RunWindow(window);
        });
    }

    public void ConfigureServices(IServiceCollection services)
    {
    }

    private static uint DebugReport(DebugReportFlagsEXT flags, DebugReportObjectTypeEXT objectType, ulong @object, UIntPtr location, int messageCode, string layerPrefix, string message, IntPtr userData)
    {
        Console.WriteLine(message);
        return 0;
    }
}
